/* 
 *  Created By: Mike Stevens
 *  Project URL: http://www.codeplex.com/sitesecuritymgmt
 *  License: GNU GPL v2
 *  Copyright (C) 2008 Mike Stevens
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 */
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using SiteSecurityManagement.Service.SecurityTree;
using SiteSecurityManagement.Entities.SecurityTree;
using Microsoft.SharePoint;
using SiteSecurityManagement.Service.SharePoint;

namespace SiteSecurityManagement.Service
{
    internal struct SecurityObject
    {
        public string[] roles;
        public string userType;
        public string user;
    }

    class BulkEditSecurityUtility
    {
        #region Members
        private const char ROLEDELIMITER = ',';

        private const string USERFRIENDLYNAME = "User";
        private const string SPGROUPFRIENDLYNAME = "SharePoint Group";
        private const string GROUPFRIENDLYNAME = "Domain Group";

        #endregion

        #region Constructor/Destructor
        #endregion

        #region Properties
        #endregion

        #region Methods
        /// <summary>
        /// Gets the security objects as defined by the userDataTable.
        /// </summary>
        /// <param name="userDataTable">The user data table.</param>
        /// <returns></returns>
        protected static List<SecurityObject> GetSecurityObjects(BulkEditSecurityDataService userDataTable)
        {
            //Set security to user specifications
            List<object[]> values = userDataTable.GetItems();
            
            List<SecurityObject> secObjects = new List<SecurityObject>(values.Count);

            for (int i = 0; i < values.Count; i++)
            {
                SecurityObject secObject = new SecurityObject();

                //get the colPermissions values
                secObject.roles = values[i][userDataTable.UserPermissionsColumnNumber].ToString().Split(new char[] { ROLEDELIMITER });
                //get the user type (user or group)
                secObject.userType = values[i][userDataTable.UserTypeColumnNumber].ToString();
                //get the user login name
                secObject.user = values[i][userDataTable.UserAccountNameColumnNumber].ToString();

                secObjects.Add(secObject);
            }

            return secObjects;
        }

        /// <summary>
        /// Gets the friendly principal.
        /// </summary>
        /// <param name="principal">The principal.</param>
        /// <returns></returns>
        public static string GetFriendlyPrincipal(string principal)
        {
            string retStr = "";

            if (principal == Enum.GetName(typeof(PrincipalTypes), PrincipalTypes.SPGroup) ||
                principal == Enum.GetName(typeof(PrincipalTypes), PrincipalTypes.SharePointGroup))
            {
                retStr = SPGROUPFRIENDLYNAME;
            }
            else if (principal == Enum.GetName(typeof(PrincipalTypes), PrincipalTypes.SPUser))
            {
                retStr = USERFRIENDLYNAME;
            }
            else if (principal == Enum.GetName(typeof(PrincipalTypes), PrincipalTypes.SecurityGroup))
            {
                retStr = GROUPFRIENDLYNAME;
            }
            else
            {
                retStr = principal;
            }
            return retStr;
        }

        /// <summary>
        /// Gets the type of the principal.
        /// </summary>
        /// <param name="principalFriendlyName">friendly name of the principal .</param>
        /// <returns></returns>
        private static PrincipalTypes GetPrincipalType(string principalFriendlyName)
        {
            switch (principalFriendlyName)
            {
                case USERFRIENDLYNAME:
                    return PrincipalTypes.SPUser;
                case GROUPFRIENDLYNAME:
                    return PrincipalTypes.SecurityGroup;
                case SPGROUPFRIENDLYNAME:
                    return PrincipalTypes.SharePointGroup;
                default:
                    return PrincipalTypes.SPUser;
            }
        }

        /// <summary>
        /// Sets the list item security.
        /// </summary>
        /// <param name="listItem">The list item.</param>
        /// <param name="dataService">The data service.</param>
        protected static void SetListItemSecurity(SPListItem listItem, BulkEditSecurityDataService dataService)
        {
            using (SPListItemSecurity listItemSec = new SPListItemSecurity(listItem))
            {
                //break inheritance and clear previous security
                listItemSec.SetInheritance(false, false);
                listItemSec.ClearSecurity();
                foreach (SecurityObject secObject in GetSecurityObjects(dataService))
                {
                    listItemSec.SetSecurity(secObject.user, GetPrincipalType(secObject.userType), secObject.roles);
                }
            }
        }

        /// <summary>
        /// Sets the file security.
        /// </summary>
        /// <param name="file">The file.</param>
        /// <param name="dataService">The data service.</param>
        protected static void SetFileSecurity(SPFile file, BulkEditSecurityDataService dataService)
        {
            using (SPFileSecurity fileSec = new SPFileSecurity(file))
            {
                //break inheritance and clear previous security
                fileSec.SetInheritance(false, false);
                fileSec.ClearSecurity();

                //Set security to user specifications
                foreach (SecurityObject secObject in GetSecurityObjects(dataService))
                {
                    fileSec.SetSecurity(secObject.user, GetPrincipalType(secObject.userType), secObject.roles);
                }
            }
        }

        /// <summary>
        /// Sets the folder security.
        /// </summary>
        /// <param name="folder">The folder.</param>
        /// <param name="dataService">The data service.</param>
        protected static void SetFolderSecurity(SPFolder folder, BulkEditSecurityDataService dataService)
        {
            using (SPFolderSecurity folderSec = new SPFolderSecurity(folder))
            {
                //break inheritance and clear previous security
                folderSec.SetInheritance(false, false);
                folderSec.ClearSecurity();

                //Set security to user specifications
                foreach (SecurityObject secObject in GetSecurityObjects(dataService))
                {
                    folderSec.SetSecurity(secObject.user, GetPrincipalType(secObject.userType), secObject.roles);
                }
            }
        }

        /// <summary>
        /// Sets the document library security.
        /// </summary>
        /// <param name="docLib">The doc lib.</param>
        /// <param name="dataService">The data service.</param>
        protected static void SetDocumentLibrarySecurity(SPDocumentLibrary docLib, BulkEditSecurityDataService dataService)
        {
            using (SPListSecurity docLibSec = new SPListSecurity(docLib))
            {
                //break inheritance and clear previous security
                docLibSec.SetInheritance(false, false);
                docLibSec.ClearSecurity();

                //Set security to user specifications
                foreach (SecurityObject secObject in GetSecurityObjects(dataService))
                {
                    docLibSec.SetSecurity(secObject.user, GetPrincipalType(secObject.userType), secObject.roles);
                }
            }
        }

        /// <summary>
        /// Sets the list security.
        /// </summary>
        /// <param name="list">The list.</param>
        /// <param name="dataService">The data service.</param>
        protected static void SetListSecurity(SPList list, BulkEditSecurityDataService dataService)
        {
            using (SPListSecurity listSec = new SPListSecurity(list))
            {
                //break inheritance and clear previous security
                listSec.SetInheritance(false, false);
                listSec.ClearSecurity();

                //Set security to user specifications
                foreach (SecurityObject secObject in GetSecurityObjects(dataService))
                {
                    listSec.SetSecurity(secObject.user, GetPrincipalType(secObject.userType), secObject.roles);
                }
            }
        }

        /// <summary>
        /// Sets the site security.
        /// </summary>
        /// <param name="site">The site.</param>
        /// <param name="dataService">The data service.</param>
        protected static void SetSiteSecurity(SPWeb site, BulkEditSecurityDataService dataService)
        {
            using (SPSiteSecurity siteSec = new SPSiteSecurity(site))
            {
                //break inheritance and clear previous security
                siteSec.SetInheritance(false, false);
                siteSec.ClearSecurity();

                //Set security to user specifications
                foreach (SecurityObject secObject in GetSecurityObjects(dataService))
                {
                    siteSec.SetSecurity(secObject.user, GetPrincipalType(secObject.userType), secObject.roles);
                }
            }
        }
        /// <summary>
        /// Sets the security.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <param name="dataService">The data service.</param>
        /// <param name="pathSeperator">The path seperator.</param>
        public static void SetSecurity(TreeNode node,BulkEditSecurityDataService dataService,char pathSeperator)
        {
            SecurityTreeUtility secTreeUtil = new SecurityTreeUtility(node, pathSeperator);
            SecurityTreeNodeTypes spObjectType = secTreeUtil.GetObjectType();

            switch (spObjectType)
            {
                case SecurityTreeNodeTypes.SPWeb:
                    {
                        using (SPWeb site = secTreeUtil.GetSite())
                        {
                            SetSiteSecurity(site,dataService);
                        }
                        break;
                    }
                case SecurityTreeNodeTypes.SPPictureLibrary:
                    {
                        SPPictureLibrary picLib = secTreeUtil.GetPictureLibrary();
                        SetListSecurity(picLib, dataService);
                        break;
                    }
                case SecurityTreeNodeTypes.SPList:
                    {
                        SPList list = secTreeUtil.GetList();
                        SetListSecurity(list, dataService);
                        break;
                    }
                case SecurityTreeNodeTypes.SPDocumentLibrary:
                    {
                        SPDocumentLibrary docLib = secTreeUtil.GetDocumentLibrary();
                        SetDocumentLibrarySecurity(docLib, dataService);
                        break;
                    }
                case SecurityTreeNodeTypes.SPFolder:
                    {
                        SPFolder folder = secTreeUtil.GetFolder();
                        SetFolderSecurity(folder, dataService);
                        break;
                    }
                case SecurityTreeNodeTypes.SPFile:
                    {
                        SPFile file = secTreeUtil.GetFile();
                        SetFileSecurity(file, dataService);
                        break;
                    }
                case SecurityTreeNodeTypes.SPListItem:
                    {
                        SPListItem listItem = secTreeUtil.GetListItem();
                        SetListItemSecurity(listItem, dataService);
                        break;
                    }
                case SecurityTreeNodeTypes.InvalidObjectType:
                    break;
            }
        }
        #endregion
    }
}
